package com.stage.calculator;

import com.stage.common.MathUtil;
import com.stage.model.SleepData;
import com.stage.model.SleepQuality;

import javax.servlet.ServletContext;
import java.sql.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;


/**
 * Created by fadinglan on 2017/4/18.
 */
public class EstimateStage extends Thread{

    CountDownLatch doneSignal;
    ServletContext context;
    Connection yun;

    private int threadIndex;
    private SleepData data;
    private static int win = 10;
    private static int step = 1;


    public EstimateStage(CountDownLatch doneSignal, int threadIndex, ServletContext context,
                         SleepData data, Connection yun){
        this.doneSignal = doneSignal;
        this.threadIndex = threadIndex;
        this.context = context;
        this.data = data;
        this.yun = yun;
    }

    @Override
    public void run(){
        SleepQuality sleepQuality = new SleepQuality();
        context.log("thread index is :" + threadIndex);

        String[] originalData = data.getHeartRate().split(" ");
//        System.out.println("data is " + originalData.toString());

        //分离心率和体动信号
        Map<String, List<Double> > spareData = ProcessSleep.SeparteRate(originalData);

        List<Double> rateList = spareData.get("rate");
        List<Double> moveList = spareData.get("move");

        //中值滤波心率信号
        List<Double> nSleepData = ProcessSleep.normSleepData(rateList);

        //阶梯化心率信号
        List<Integer> sSleepData = ProcessSleep.stairHeart(nSleepData);

        //计算分期
        HMM hmm = new HMM(sSleepData.toArray(new Integer[sSleepData.size()]));

        initAandB();
        List<Integer> stageList = hmm.excute();
        if (stageList.size() != 0){
            System.out.println("========分期开始=======");
            for (Integer ss : stageList){
                System.out.println(ss);
            }

            System.out.println("==========分期结束===========");

            String strStage = MathUtil.array2String(stageList).toString();

            //判断入睡
            //判断入睡时间
            int count = 0;
            short sleepFlag = 0;
            Integer[] range;
            Integer[] sleepStage = stageList.toArray(new Integer[stageList.size()]);

            for (int i = 0; i < sleepStage.length - win + 1; i += step){
                range = Arrays.copyOfRange(sleepStage, i, i + win);
                int sleepCount = 0;
                for (int j = 0; j < range.length; j++){
                    if (range[j] < 4) {
                        sleepCount++;
                    }
                }

                if (sleepCount > 7){
                    count = i+win;
                    sleepFlag = 1;
                    System.out.println("已经入睡");
                    break;
                }
            }

            String falAsleepTime = calAsleepTime(data.getStartTime(), count);
//
            //判断觉醒
            int awakeTimeCount = 0;
            Integer[] awakeRange;
            for (int i = sleepStage.length - win - 1; i > win; i -= step){

                awakeRange = Arrays.copyOfRange(sleepStage, i, i + win);
                int awakeCount = 0;
                for (int j = 0; j < awakeRange.length; j++){
                    if (awakeRange[j] == 4){
                        awakeCount ++;
                    }
                }

                if (awakeCount > 7){
                    awakeTimeCount  = i + win;
                    System.out.println("已经觉醒");
                    break;
                }
            }
            String awakeTime = calAsleepTime(data.getStartTime(), awakeTimeCount);

            sleepQuality.setDeviceId(data.getDeviceId());
            sleepQuality.setSleepState(strStage);
            sleepQuality.setSleepFlag(sleepFlag);
            sleepQuality.setSleepDate(data.getStartTime());
            sleepQuality.setWakeTime(awakeTime);
            sleepQuality.setFallAsleepTime(falAsleepTime);


        sleepQuality.setFallAsleepDuration(8.1);
        sleepQuality.setLightSleep(2.1);
        sleepQuality.setSleepDuration(9.1);
        sleepQuality.setFallAsleepDuration(0.5);
        sleepQuality.setDeepSleep(2.0);
        sleepQuality.setDreamSleep(2.0);
        sleepQuality.setEfficiency(89);
        sleepQuality.setSleepLeave(1);
        sleepQuality.setSleepMove(2);
        sleepQuality.setSleepTimePoint(strStage);

            insertOrUpdate(sleepQuality);
        }

        doneSignal.countDown();

    }

    private void insertOrUpdate(SleepQuality quality){
        int sleepQualiteId = queryInQuality(quality);
        String sql = null;
        PreparedStatement ps = null;
        try {
            if (sleepQualiteId == -1){  //记录不存在 执行插入操作
                context.log("记录不存在，插入数据库");

                sql = "insert into sleep_quality(deepSleep,deviceId,dreamSleep,efficiency,fallAsleepDuration,fallAsleepTime," +
                        "lightSleep,OffBedTime,sleepDate,sleepDuration,sleepFlag,sleepLeave,sleepMove,sleepState,sleepTimePoint,wakeTime)" +
                        " values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
//                sql = "insert into sleep_quality (deviceId,sleepDate,fallAsleepTime,sleepState,sleepFlag) values(?, ?, ?, ?, ?)";

                ps = yun.prepareStatement(sql);
//                ps.setLong(1, quality.getDeviceId());
//                ps.setString(2, quality.getSleepDate());
//                ps.setString(3, quality.getFallAsleepTime());
//                ps.setString(4, quality.getSleepState());
//                ps.setInt(5, quality.getSleepFlag());
//                ps.setString(6, quality.getSleepTimePoint());

                ps.setDouble(1, quality.getDeepSleep());
                ps.setLong(2, quality.getDeviceId());
                ps.setDouble(3, quality.getDreamSleep());
                ps.setInt(4, quality.getEfficiency());
                ps.setDouble(5, quality.getFallAsleepDuration());
                ps.setString(6, quality.getFallAsleepTime());
                ps.setDouble(7, quality.getLightSleep());
                ps.setString(8, quality.getOffBedTime());
                ps.setString(9, quality.getSleepDate());
                ps.setDouble(10, quality.getSleepDuration());
                ps.setInt(11, quality.getSleepFlag());
                ps.setInt(12, quality.getSleepLeave());
                ps.setLong(13, quality.getSleepMove());
                ps.setString(14, quality.getSleepState());
                ps.setString(15, quality.getSleepTimePoint());
                ps.setString(16, quality.getWakeTime());

//                ps.executeUpdate();
                context.log("插入成功");

            }else {     //更新数据
                context.log("数据存在，更新数据");

                sql = "update sleep_quality set sleepState = '" + quality.getSleepState() + "', sleepFlag = " + quality.getSleepFlag()
                        + ", sleepTimePoint = '" + quality.getSleepTimePoint() + "' where sleepQualityId = " + sleepQualiteId;
                ps = yun.prepareStatement(sql);

                context.log("更新成功");
            }
            ps.executeUpdate();
            yun.commit();

        }catch (SQLException e){
            try {
                context.log("更新数据库异常");
                yun.rollback();
            }catch (SQLException e1){
                e1.printStackTrace();
            }
            e.printStackTrace();
        }finally {
            if (ps != null){
                try {
                    ps.close();
                }catch (SQLException e){
                    e.printStackTrace();
                }
            }
        }

    }


    private int queryInQuality(SleepQuality quality){
        int qualityId = -1;

        String sql = "select * from sleep_quality where deviceId = " + quality.getDeviceId()
                + " and sleepDate = '" + quality.getSleepDate() + "'";

        PreparedStatement ps = null;
        ResultSet rs = null;
        try{
            ps = yun.prepareStatement(sql);
            rs = ps.executeQuery();
            yun.commit();
            while (rs.next()){
                qualityId = rs.getInt("sleepQualityId");

            }
        }catch (SQLException e){
            try {
                System.out.println("查询数据库异常==");
                yun.rollback();
            }catch (SQLException e1){
                e1.printStackTrace();
            }
            e.printStackTrace();
        }finally {
            if (rs != null){
                try {
                    rs.close();
                }catch (SQLException e){
                    e.printStackTrace();
                }
            }

            if (ps != null){
                try {
                    ps.close();
                }catch (SQLException e){
                    e.printStackTrace();
                }
            }
        }

        return qualityId;

    }


    /**
     * 入睡时间判断：计算入睡时间
     * @param startTime
     * 睡眠开始时间
     * @param count
     * 睡眠分期计数   1 count = 30s
     * @return
     */
    private String calAsleepTime(String startTime, int count) {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String sleepTime = startTime;
        try {
            //字符串转日期
            Date startDate = sdf.parse(startTime);

            Date sleepDate = new Date(startDate .getTime() + count*30*1000);
            sleepTime = sdf.format(sleepDate);

        } catch (ParseException e) {
            e.printStackTrace();
        }
        return sleepTime;

    }

    private void initAandB(){

        HMM.AW = HMM.readArray(context.getRealPath("resource/h_W_A.txt"));
        HMM.AR = HMM.readArray(context.getRealPath("resource/h_R_A.txt"));
        HMM.A1 = HMM.readArray(context.getRealPath("resource/h_S1_A.txt"));
        HMM.A2 = HMM.readArray(context.getRealPath("resource/h_S2_A.txt"));
        HMM.A3 = HMM.readArray(context.getRealPath("resource/h_S3_A.txt"));
        HMM.A4 = HMM.readArray(context.getRealPath("resource/h_S4_A.txt"));

        HMM.BW = HMM.readArray(context.getRealPath("resource/h_W_B.txt"));
        HMM.BR = HMM.readArray(context.getRealPath("resource/h_R_B.txt"));
        HMM.B1 = HMM.readArray(context.getRealPath("resource/h_S1_B.txt"));
        HMM.B2 = HMM.readArray(context.getRealPath("resource/h_S2_B.txt"));
        HMM.B3 = HMM.readArray(context.getRealPath("resource/h_S3_B.txt"));
        HMM.B4 = HMM.readArray(context.getRealPath("resource/h_S4_B.txt"));
    }

}
